﻿using HMS.Core.Abstractions;
using HMS.Hosting.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Net;

namespace HMS.Hosting.Authentication;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddMultiTenantAuthentication(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddHttpClient("oauth").ConfigurePrimaryHttpMessageHandler(provider =>
        {
            return new HttpClientHandler()
            {
                ServerCertificateCustomValidationCallback = delegate { return true; },
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
            };
        });

        services.AddAuthentication(opts =>
        {
            opts.DefaultAuthenticateScheme = "Default";
            opts.DefaultChallengeScheme = "Default";
            opts.RequireAuthenticatedSignIn = false;
        }).AddScheme<DefaultAuthenticationOptions, DefaultAuthenticationHandlerPlatform>("Default", null);

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
            {
                options.SlidingExpiration = true;
                options.SessionStore = new MemoryTicketStore();
                options.DataProtectionProvider = new CookieDataProtector();
                options.ForwardAuthenticate = "External:IdSrv";
            });

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer("External:IdSrv", opts =>
            {
                opts.BackchannelHttpHandler = new HttpClientHandler()
                {
                    ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
                };

                var issuer = configuration["Jwt:Issuer"];
                var audience = configuration["Jwt:Audience"];
                var securityKey = configuration["Jwt:SecurityKey"];

                var symmetricKey = new SymmetricSecurityKey(Convert.FromBase64String(securityKey!));

                opts.RequireHttpsMetadata = !string.IsNullOrWhiteSpace(opts.Authority) &&
                    opts.Authority.StartsWith("https://", StringComparison.OrdinalIgnoreCase);

                opts.Events = new JwtBearerEvents
                {
                    OnTokenValidated = (ctx) =>
                        ctx.HttpContext.RequestServices.GetService<ITenantService>()?.Validate(ctx) ?? Task.CompletedTask
                };

                opts.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidIssuer = issuer,
                    ValidAudience = audience,
                    IssuerSigningKey = symmetricKey,

                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateIssuerSigningKey = true,

                    ValidateLifetime = true,
                    RequireExpirationTime = true,
                    ClockSkew = TimeSpan.FromMinutes(30)
                };
                opts.SaveToken = true;
                opts.IncludeErrorDetails = true;

                IdentityModelEventSource.ShowPII = true;
            });

        return services;
    }
}